﻿using System.Reflection;
using System.Windows;
using Fluffy.Archive;
using Fluffy.FakeDocument;
using Fluffy.FileMenuCommands;
using Fluffy.Library.DocumentContainer;
using Fluffy.Library.FileSources;
using Fluffy.Library.Logging;
using Fluffy.Library.Mvvm;
using Fluffy.Library.Mvvm.Commands;
using Fluffy.Library.Utils;
using Fluffy.Text;
using Fluffy.Torrent;
using Fluffy.Viewes;
using System;
using System.Diagnostics;
using System.Windows.Input;
using Raccoom.Xml;

namespace Fluffy
{
	internal class MainWindowViewModel : ViewModelBase
    {
		private readonly MainWindowModel _model = new MainWindowModel();
		private readonly OpenCommandViewModel _openCommandViewModel;
		private readonly NewCommandViewModel _newCommandViewModel;

		private MainViewState _mainViewState = MainViewState.Start;
		private ViewModelBase _currentFileMenuOperation;
		private DocumentViewModelBase _currentFileContainer;

		public MainWindowViewModel()
		{
			_model.FileSourceChanged += OnFileSourceChanged;
			_model.FileContainerRecreated += OnFileContainerRecreated;

			string[] commandLineArgs = Environment.GetCommandLineArgs();
			if (commandLineArgs.Length > 1)
			{
				string arg = commandLineArgs[1];

				if (arg.StartsWith("magnet:", StringComparison.InvariantCultureIgnoreCase))
					_model.OpenCommand.OpenLink(arg);
				else
					_model.OpenCommand.OpenFile(arg);
			}

			_newCommandViewModel = new NewCommandViewModel(_model.NewCommand);
			_openCommandViewModel = new OpenCommandViewModel(_model.OpenCommand);
			_currentFileMenuOperation = _openCommandViewModel;
		}
		
		public ViewModelBase CurrentFileMenuOperation
		{
			get { return _currentFileMenuOperation; }
			set
			{
				if (_currentFileMenuOperation == value)
					return;

				_currentFileMenuOperation = value;
				OnPropertyChanged("CurrentFileMenuOperation");
			}
		}

		public ViewModelBase OpenCommandViewModel
		{
			get { return _openCommandViewModel; }
		}

		public ViewModelBase NewCommandViewModel
		{
			get { return _newCommandViewModel; }
		}

		public DocumentViewModelBase CurrentFileContainer
		{
			get { return _currentFileContainer; }
			set
			{
				if (_currentFileContainer == value)
					return;

				_currentFileContainer = value;

				OnPropertyChanged("CurrentFileContainer");
				OnPropertyChanged("ApplicationTitle");
				OnPropertyChanged("IsOpenedAsArchive");
			}
		}

		public MainViewState ViewState
		{
			get { return _mainViewState; }
			set
			{
				if (value == _mainViewState)
					return;

				_mainViewState = value;
				OnPropertyChanged("ViewState");
				OnPropertyChanged("IsContentView");
				OnPropertyChanged("IsFileMenuView");
				OnPropertyChanged("IsStartView");
			}
		}

		public bool IsContentView
		{
			get { return _mainViewState == MainViewState.Content; }
		}

		public bool IsFileMenuView
		{
			get { return _mainViewState == MainViewState.FileMenu; }
		}

		public bool IsStartView
		{
			get { return _mainViewState == MainViewState.Start; }
		}

		public ICommand FileViewCommand
		{
			get { return new Command(OnOpenFileView); }
		}

		public ICommand ContentViewCommand
		{
			get { return new Command(OnOpenContentView); }
		}

		public ICommand OpenCommand
		{
			get { return new Command(OnOpen); }
		}

		public ICommand NewCommand
		{
			get { return new Command(OnNew); }
		}

		public ICommand PrintCommand
		{
			get { return new DisabledCommand(); }
		}

		public ICommand ShareCommand
		{
			get { return new DisabledCommand(); }
		}

		public ICommand ExportCommand
		{
			get { return new DisabledCommand(); }
		}

		public ICommand OptionsCommand
		{
			get { return new DisabledCommand(); }
		}

		public ICommand BrowseForOpenDocumentCommand
		{
			get { return _openCommandViewModel.OpenDocumentCommand; }
		}

		public ICommand CloseCommand
		{
			get { return new Command(OnClose); }
		}

		private void OnFileContainerRecreated()
		{
			CurrentFileContainer = new FakeDocument.FakeDocument().GenerateViewModel(new NewFile());
			CurrentFileContainer = _model.SourceFileContainer;
		}
		
		private void OnFileSourceChanged()
		{
			ViewState = MainViewState.Content;
			OnPropertyChanged("ApplicationTitle");
		}

		private void OnOpen()
		{
			ViewState = MainViewState.FileMenu;
			CurrentFileMenuOperation = new OpenCommandViewModel(_model.OpenCommand);
		}

		private void OnNew()
		{
			ViewState = MainViewState.FileMenu;
			CurrentFileMenuOperation = new NewCommandViewModel(_model.NewCommand);
		}

		private void OnClose()
		{
			ViewState = MainViewState.Content;
			CurrentFileContainer = null;
		}

		public string ApplicationTitle
		{
			get { return CurrentFileContainer == null ? AppConstants.AppName : AppConstants.AppName + " - " + _model.SourceFile.FileName; }
		}

		public ICommand WebsiteCommand
		{
			get { return new Command(OnWebsite); }
		}

		public ICommand DocumentationCommand
		{
			get { return new Command(OnDocumentation); }
		}

		public ICommand UpdateCommand
		{
			get { return new Command(() => OnCheckUpdate(true)); }
		}

		public ICommand AboutCommand
		{
			get { return new Command(OnAbout); }
		}

		public bool IsOpenedAsArchive
		{
			get { return _model.SourceFileContainer is ArchiveDocumentViewModel; }
			set
			{
				if (value)
				{
					try
					{
						_model.ReopenAsAchive();
					}
					catch (Exception exception)
					{
						LoggerView.Log(exception);
					}
				}
			}
		}

		public bool IsOpenedAsTorrent
		{
			get { return _model.SourceFileContainer is TorrentDocumentViewModel; }
			set
			{
				if (value)
				{
					try
					{
						_model.ReopenAsTorrent();
					}
					catch (Exception exception)
					{
						LoggerView.Log(exception);
					}
				}
			}
		}

		public bool IsOpenedAsText
		{
			get { return _model.SourceFileContainer is TextDocumentViewModel; }
			set
			{
				if (value)
				{
					try
					{
						_model.ReopenAsText();
					}
					catch (Exception exception)
					{
						LoggerView.Log(exception);
					}
				}
			}
		}

		public ICommand WindowClosedCommand
		{
			get { return new Command(OnWindowClosed); }
		}

		public ICommand WindowLoadedCommand
		{
			get { return new Command(OnWindowLoaded); }
		}

		private void OnWindowLoaded()
		{
			ThreadUtils.StartThread(() => OnCheckUpdate(false));
		}

		private void OnWindowClosed()
		{
			if (_model.SourceFileContainer != null)
				_model.SourceFileContainer.Close();
		}

		private void OnAbout()
		{
			AboutView dialog = new AboutView();
			dialog.ShowDialog();
		}

		private void OnDocumentation()
		{
			Process.Start("http://fluffy.codeplex.com/documentation");
		}

		private void OnWebsite()
		{
			Process.Start("http://fluffy.codeplex.com/");
		}

		private void OnOpenFileView()
		{
			ViewState = MainViewState.FileMenu;
		}

		private void OnOpenContentView()
		{
			ViewState = MainViewState.Content;
		}
		
		private void OnCheckUpdate(bool withAdditionalUi)
		{
			try
			{
				Uri uri = new Uri("http://fluffy.codeplex.com/project/feeds/rss?ProjectRSSFeed=codeplex%3a%2f%2frelease%2ffluffy");
				RssChannel myRssChannel = new RssChannel(uri);
				Version currentVersion = Assembly.GetExecutingAssembly().GetName().Version;

				for (int index = 0; index < myRssChannel.Items.Count; index++)
				{
					RssItem item = myRssChannel.Items[index];
					string title = item.Title;

					if (!title.Contains(AppConstants.AppName))
						continue;

					string appName = title.Substring(title.IndexOf(AppConstants.AppName, StringComparison.InvariantCultureIgnoreCase));
					string version = appName.Substring(AppConstants.AppName.Length);

					if (version.Contains("("))
						version = version.Substring(0, version.IndexOf("(", StringComparison.InvariantCultureIgnoreCase));

					version = version.Trim();

					Version newVersion;
					if (Version.TryParse(version, out newVersion) && newVersion.Revision > currentVersion.Revision)
					{
						Application.Current.Dispatcher.Invoke(() =>
						{
							MessageBoxResult result = MessageBox.Show(Application.Current.MainWindow, "The newer version of this program is available. Do you want to download it?", "Update",
																	  MessageBoxButton.OKCancel, MessageBoxImage.Information);

							if (result == MessageBoxResult.OK)
								Process.Start(item.Link);
						});

						return;
					}
				}

				if (withAdditionalUi)
				{
					Application.Current.Dispatcher.Invoke(() => MessageBox.Show(App.Current.MainWindow, "You have the latest version of this program.", "Update",
						MessageBoxButton.OK, MessageBoxImage.Information));
				}
			}
			catch (Exception exception)
			{
				if (withAdditionalUi)
					LoggerView.Log(exception);
			}
		}

		public enum MainViewState
		{
			Start,
			FileMenu,
			Content
		}
    }
}
